#include "Connection.h"

Network::Connection::Connection()
{
	this->_socketInfosLenght = sizeof(this->_socketInfos);
}

#ifdef _WIN32
Network::Connection::Connection(const std::string& address, unsigned short port, SOCKET socket, SOCKADDR_IN socketInfos)
#else
Network::Connection::Connection(const std::string& address, unsigned short int port, unsigned int socket, sockaddr_in socketInfos);
#endif
: _address(address), _port(port), _socket(socket), _socketInfos(socketInfos)
{
	this->_socketInfosLenght = sizeof(this->_socketInfos);
}

Network::Connection::~Connection()
{
}

unsigned int	Network::Connection::CreateSocket()
{
	this->_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#ifdef _WIN32
	if (this->_socket == INVALID_SOCKET)
#else
	if (this->_socket < 0)
#endif
		return (1);
	this->_socketInfos.sin_family = AF_INET;
	return (0);
}

unsigned int	Network::Connection::BindSocket(unsigned short int port, const std::string& address)
{
	if (address == "ANYADDR")
		this->_socketInfos.sin_addr.S_un.S_addr = INADDR_ANY;
	else
		this->_socketInfos.sin_addr.S_un.S_addr = inet_addr(address.c_str());
	this->_socketInfos.sin_port = htons(port);
#ifdef _WIN32
	if (bind(this->_socket, (SOCKADDR*)(&(this->_socketInfos)), this->_socketInfosLenght) != 0)
#else
	if (bind(this->_socket, (sockaddr*)(&(this->_socketInfos)), this->_socketInfosLenght) != 0)
#endif
		return (1);
	this->_address = address;
	this->_port = port;
	return (0);
}

unsigned int	Network::Connection::CloseSocket()
{
#ifdef _WIN32
	if (closesocket(this->_socket) == SOCKET_ERROR)
#else
	if (close(this->_socket))
#endif
		return (1);
	return (0);
}

unsigned int	Network::Connection::ReceiveData(void* data, unsigned int* size, timeval* timeout)
{
	int	sz = *size;

	*size = 0;
	if (timeout)
	{
		int		state;
		fd_set	fd;

		FD_ZERO(&fd);
		FD_SET(this->_socket, &fd);
		state = select(1, &fd, NULL, NULL, timeout);
		if (state > 0)
		{
			if (!FD_ISSET(this->_socket, &fd))
				return (4);	
		}
		else if (state == 0)
			return (0);
		else if (state < 0)
			return (2);
	}
	if ((sz = recv(this->_socket, (char*)data, sz, 0)) < 0)
		return (3);
	*size = static_cast<unsigned int>(sz);
	return (0);
}

unsigned int	Network::Connection::SendData(void* data, unsigned int* size, timeval* timeout)
{
	int	sz = *size;

	*size = 0;
	if (timeout)
	{
		int		state;
		fd_set	fd;

		FD_ZERO(&fd);
		FD_SET(this->_socket, &fd);
		state = select(1, NULL, &fd, NULL, timeout);
		if (state > 0)
		{
			if (!FD_ISSET(this->_socket, &fd))
				return (4);	
		}
		else if (state == 0)
			return (0);
		else if (state < 0)
			return (2);
	}
	if ((sz = send(this->_socket, (char*)data, sz, 0)) < 0)
		return (3);
	*size = static_cast<unsigned int>(sz);
	return (0);
}

const std::string&	Network::Connection::GetAddress() const
{
	return (this->_address);
}

unsigned short int	Network::Connection::GetPort() const
{
	return (this->_port);
}
